package com.hwpt.utils;

import java.time.Instant;
import java.util.concurrent.atomic.AtomicLong;

/**
 * ID生成工具类
 * 格式：hw_ + 8位纯数字（4位秒级时间戳后4位 + 4位序列号）
 */
public final class IdGeneratorUtil {

    private IdGeneratorUtil() {
        throw new UnsupportedOperationException("工具类不允许实例化");
    }

    // 最后时间戳（毫秒级）
    private static final AtomicLong LAST_TIMESTAMP = new AtomicLong(0);
    // 序列号计数器（同一时间戳内递增）
    private static final AtomicLong COUNTER = new AtomicLong(0);
    // 最大序列号（同一时间戳内最多9999个，避免溢出）
    private static final long MAX_SEQUENCE = 9999L;

    /**
     * 生成hw_格式的8位纯数字ID
     * @return 格式为hw_xxxxxxxx的ID字符串（如 hw_12345678）
     */
    public static String generateHwId() {
        long currentTimestamp = getCurrentTimestamp();
        long lastTimestamp;
        long sequence;

        // 循环确保时间戳递增+序列号不溢出
        while (true) {
            lastTimestamp = LAST_TIMESTAMP.get();
            
            if (currentTimestamp > lastTimestamp) {
                // 新时间戳：重置序列号，更新最后时间戳
                if (LAST_TIMESTAMP.compareAndSet(lastTimestamp, currentTimestamp)) {
                    COUNTER.set(0);
                    sequence = 0;
                    break;
                }
            } else if (currentTimestamp == lastTimestamp) {
                // 同一时间戳：递增序列号，判断是否溢出
                sequence = COUNTER.incrementAndGet();
                if (sequence <= MAX_SEQUENCE) {
                    break;
                }
                // 序列号溢出：等待下一毫秒
                currentTimestamp = waitForNextTimestamp(currentTimestamp);
            } else {
                // 时钟回拨：等待时间追赶上最后记录的时间戳
                currentTimestamp = waitForNextTimestamp(lastTimestamp);
            }
        }

        return formatId(currentTimestamp, sequence);
    }

    /**
     * 批量生成ID
     * @param count 生成数量（需大于0）
     * @return ID数组
     */
    public static String[] generateHwIds(int count) {
        if (count <= 0) {
            throw new IllegalArgumentException("生成数量必须大于0");
        }

        String[] ids = new String[count];
        for (int i = 0; i < count; i++) {
            ids[i] = generateHwId();
        }
        return ids;
    }

    /**
     * 获取当前毫秒级时间戳
     */
    private static long getCurrentTimestamp() {
        return Instant.now().toEpochMilli();
    }

    /**
     * 等待直到时间戳超过目标值（处理时钟回拨/序列号溢出）
     * 增加1ms休眠避免CPU空转
     */
    private static long waitForNextTimestamp(long targetTimestamp) {
        long timestamp = getCurrentTimestamp();
        while (timestamp <= targetTimestamp) {
            timestamp = getCurrentTimestamp();
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("ID生成器等待时间戳时被中断", e);
            }
        }
        return timestamp;
    }

    /**
     * 格式化ID：4位秒级时间戳后4位 + 4位序列号
     */
    private static String formatId(long timestamp, long sequence) {
        // 转秒级时间戳（减少位数，降低重复概率）
        long secondTimestamp = timestamp / 1000;
        // 截取秒级时间戳后4位（补0确保4位）
        String timestampPart = String.format("%04d", secondTimestamp % 10000);
        // 序列号补0确保4位
        String sequencePart = String.format("%04d", sequence);
        
        return "hw_" + timestampPart + sequencePart;
    }
}
